package ru.osu.acm.common.industrial;

import ru.osu.acm.common.entities.Testcase;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 * User: aleksey
 * Date: Sep 22, 2009
 * Time: 4:17:18 PM
 */
public class TestcaseFactory extends Factory {
    public static Testcase getTestcase(int testcaseId, Connection con, boolean closeConnection) {
        Testcase testcase = null;

        try {
            PreparedStatement statement = con.prepareStatement("select * from testcase where id = ?");
            statement.setInt(1, testcaseId);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                testcase = new Testcase(
                        resultSet.getInt("id"),
                        resultSet.getInt("testindex"),
                        ProblemFactory.getProblem(resultSet.getInt("problem"), con, false),
                        resultSet.getString("inputtext"),
                        resultSet.getString("outputtext")
                        );
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
        return testcase;
    }

    public static String getInputTestcase(int problemId, int testIndex, Connection con, boolean closeConnection) {
        String input = "";

        try {
            PreparedStatement statement = con.prepareStatement("select * from testcase where problem = ? and testindex = ?");
            statement.setInt(1, problemId);
            statement.setInt(2, testIndex);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                input = resultSet.getString("inputtext").trim();
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
        return input;
    }

    public static String getOutputTestcase(int problemId, int testIndex, Connection con, boolean closeConnection) {
        String output = "";

        try {
            PreparedStatement statement = con.prepareStatement("select * from testcase where problem = ? and testindex = ?");
            statement.setInt(1, problemId);
            statement.setInt(2, testIndex);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                output = resultSet.getString("outputtext").trim();
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
        return output;
    }

    public static int getTestCountForProblem(int problemId, Connection con, boolean closeConnection) {
        int count = 0;

        try {
            PreparedStatement statement = con.prepareStatement("select count(*) as testcount from testcase where problem = ?");
            statement.setInt(1, problemId);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                count = resultSet.getInt("testcount");
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
        return count;
    }

    public static ArrayList<Testcase> getTestsForProblem(int problemId, Connection con, boolean closeConnection) {
        ArrayList<Testcase> tests = new ArrayList<Testcase>();

        try {
            PreparedStatement statement = con.prepareStatement("select * from testcase where problem = ? order by testindex");
            statement.setInt(1, problemId);
            ResultSet resultSet = statement.executeQuery();
            while (resultSet.next()) {
                tests.add(new Testcase(
                        resultSet.getInt("id"),
                        resultSet.getInt("testindex"),
                        ProblemFactory.getProblem(resultSet.getInt("problem"), con, false),
                        resultSet.getString("inputtext"),
                        resultSet.getString("outputtext")
                ));
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
        return tests;
    }

    public static void updateTestcase(Testcase testcase, Connection con, boolean closeConnection) {
        if (testcase.getId() == -1) {
            testcase.setId(getNextId("testcase", con, false));

            try {
                PreparedStatement statement = con.prepareStatement("insert into testcase (id, problem, testindex, " +
                        "inputtext, outputtext) values (?, ?, ?, ?, ?)");
                statement.setInt(1, testcase.getId());
                statement.setInt(2, testcase.getProblem().getId());
                statement.setInt(3, testcase.getIndex());
                statement.setString(4, testcase.getInput());
                statement.setString(5, testcase.getOutput());
                statement.executeUpdate();
                statement.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }

            closeConnection(con, closeConnection);
            return;
        }

        try {
            PreparedStatement statement = con.prepareStatement("update testcase set problem = ?, testindex = ?, " +
                        "inputtext = ?, outputtext = ? where id = ?");
            statement.setInt(1, testcase.getProblem().getId());
            statement.setInt(2, testcase.getIndex());
            statement.setString(3, testcase.getInput());
            statement.setString(4, testcase.getOutput());
            statement.setInt(5, testcase.getId());
            statement.executeUpdate();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
    }

    public static void deleteTestcase(int testcaseId, int problemId, Connection con, boolean closeConnection) {
        int index = 0;

        try {
            PreparedStatement statement = con.prepareStatement("select testindex from testcase where id = ?");
            statement.setInt(1, testcaseId);
            ResultSet resultSet = statement.executeQuery();
            if (resultSet.next()) {
                index = resultSet.getInt("testindex");
            }
            resultSet.close();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            PreparedStatement statement = con.prepareStatement("update testcase set testindex = testindex - 1 where problem = ? and testindex > ?");
            statement.setInt(1, problemId);
            statement.setInt(2, index);
            statement.executeUpdate();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            PreparedStatement statement = con.prepareStatement("delete from testcase where id = ?");
            statement.setInt(1, testcaseId);
            statement.executeUpdate();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
    }

    public static void deleteAllTests(int problemId, Connection con, boolean closeConnection) {
        try {
            PreparedStatement statement = con.prepareStatement("delete from testcase where problem = ?");
            statement.setInt(1, problemId);
            statement.executeUpdate();
            statement.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }

        closeConnection(con, closeConnection);
    }

    public static Testcase getNewTestcase() {
        return new Testcase(-1, 0, null, "", "");
    }
}
